package com.mxpio.erp.common.order.policy;

import java.util.Date;
import java.util.List;
import java.util.Map;

import com.mxpio.erp.common.LotStatusUtil;
import com.mxpio.erp.common.inventory.entity.Lot;
import com.mxpio.erp.common.jpa.model.LotKey;
import org.apache.commons.collections4.CollectionUtils;

import com.mxpio.erp.common.enums.NoticeStatusEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.inventory.entity.WarehouseOrder;
import com.mxpio.erp.common.inventory.entity.WarehouseOrderLine;
import com.mxpio.erp.common.jpa.entity.BizNoticeType;
import com.mxpio.erp.common.jpa.model.Notice;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpioframework.jpa.JpaUtil;
import org.apache.commons.lang3.StringUtils;

/**
 * 根据策略执行通知单
 *
 */
public abstract class AbstractNoticePolicy implements NoticePolicy {
	
	@Override
	public void apply(NoticeContext context) {
		if(beforeExecute(context)) {
			execute(context);
			Notice notice = context.getEntity();
			List<OrderExcuteLineVo> orderExcuteVos = context.getOrderExcuteVos();
			WarehouseOrder wo = null;
			int lineNo = 0;
			List<BizNoticeType> bizNoticeTypes = JpaUtil.linq(BizNoticeType.class).list();
			Map<String, BizNoticeType> typesMap = JpaUtil.index(bizNoticeTypes);
			
			for(OrderExcuteLineVo vo : orderExcuteVos){
				lineNo++;
				if(wo == null){
					wo = new WarehouseOrder();
					wo.setAccessType(notice.getAccessType());
					wo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
					wo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
					wo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
					wo.setOrderDate(new Date());
					wo.setOriginBizNo(StringUtils.isBlank(vo.getBizOrderNo())?vo.getNoticeNo():vo.getBizOrderNo());//20221012 wpp 如果是由手工录入的通知单（物资系统操作），那么此处bizOrderNo会为空
					wo.setWhCode(vo.getWhCode());
					wo.setWoType(notice.getPickingType());
					wo.setOriginNoticeNo(notice.getNoticeNo());//关联noticeno字段
					JpaUtil.save(wo);
				}
				WarehouseOrderLine line = new WarehouseOrderLine();
				line.setWhCode(wo.getWhCode());
				line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
				Item item = JpaUtil.linq(Item.class).idEqual(vo.getItemCode()).findOne();
				line.setItemCode(vo.getItemCode());
				line.setItemGroupCode(item.getItemGroupCode());
				line.setItemName(item.getItemName());
				line.setItemSpec(item.getItemSpec());
				line.setUnitCode(item.getUnitCode());
				line.setDrawingNo(item.getDrawingNo());
				line.setQuantity(vo.getQuantity());
				line.setBizNo(wo.getBizNo());
				line.setLineNo(lineNo+"");
				//line.setOriginBizNo(vo.getBizOrderNo());
				line.setOriginBizNo(StringUtils.isBlank(vo.getBizOrderNo())?vo.getNoticeNo():vo.getBizOrderNo());
				//line.setOriginBizLineNo(vo.getBizOrderlineNo());
				line.setOriginBizLineNo(StringUtils.isBlank(vo.getBizOrderlineNo())?vo.getNoticeLineNo():vo.getBizOrderlineNo());//考虑资产手动新增通知单的情况
				line.setSort(vo.getSort());
				if(StringUtils.isNotBlank(vo.getLotNo())){
					line.setLotNo(vo.getLotNo());
					line.setSubLotIndex(vo.getSubLotIndex());
					if (StringUtils.equals("in",notice.getAccessType())){
						String subLotIndex = StringUtils.isBlank(vo.getSubLotIndex())?"0":vo.getSubLotIndex();
						LotKey lotKey = new LotKey();
						lotKey.setLotNo(vo.getLotNo());
						lotKey.setSubLotIndex(subLotIndex);
						Lot dbLot = JpaUtil.getOne(Lot.class, lotKey);
						if (dbLot==null){//保存批次
							Lot lot = new Lot();
							lot.setLotNo(vo.getLotNo());
							lot.setLotStatus(LotStatusUtil.toBinaryString("0"));
							lot.setSubLotIndex("0");
							JpaUtil.save(lot);
							line.setSubLotIndex(lot.getSubLotIndex());
						}else{
							line.setSubLotIndex(dbLot.getSubLotIndex());
						}
					}
				}else if(context.getLotService() == null){
					line.setLotNo("none");
				}else{
					if (!(StringUtils.equals(notice.getPickingType(),NoticeStatusEnums.NoticeType.TO_IN.getCode()))&&StringUtils.equals("in",notice.getAccessType())){//指定出入类型，控制通知单执行逻辑中，是否需要生成批次（排除调拨入）
						Lot newLot = context.getLotService().getNewLot(notice, vo, typesMap);
						if (newLot!=null){
							line.setLotNo(newLot.getLotNo());
							line.setSubLotIndex(newLot.getSubLotIndex());
						}else{
							line.setLotNo("none");
							line.setSubLotIndex("0");
						}
					}
				}
				line.setOriginNoticeNo(notice.getNoticeNo());
				line.setOriginNoticeLineNo(vo.getNoticeLineNo());
				JpaUtil.save(line);
			}
			afterExecute(context);
			notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CONFIRM.getStatusCode());
			JpaUtil.update(notice);
		} else {
			if(CollectionUtils.isEmpty(context.getErrors())) {
				context.addError("前置校验不通过");
			}
		}
		
	}
	
	public abstract void execute(NoticeContext context);
	
	public abstract boolean beforeExecute(NoticeContext context);

	public abstract void afterExecute(NoticeContext context);

}
